////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file   CollabRCBot\OperationTreeNodeImpl.h
///
/// @brief  Defines various operators for genetic algorithms
////////////////////////////////////////////////////////////////////////////////////////////////////

#pragma once

#include "OperationTreeNode.h"
#include "ComputationalTreeNodeVisitor.h"

namespace CollabRC
{
    namespace Bot
    {
        namespace AI
        {
            /**
             * @brief Implementation of an OperationTreeNode which
             * handles the specified operation.
             * @version $Id$
             * @author Matthew P. Del Buono
             * @param n the name of the class
             * @param o the operation to perform
             */
#define CREATE_OPERATION_TREE_NODE(n, o)                                                            \
            class n : public OperationTreeNode                                                      \
            {                                                                                       \
            private:                                                                                \
                class Factory : public OperationTreeNode::OperationTreeNodeFactory                  \
                {                                                                                   \
                public:                                                                             \
                    Factory()                                                                       \
                    {                                                                               \
                        OperationTreeNode::RegisterOperationTreeNodeFactory(this);                  \
                    }                                                                               \
                                                                                                    \
                    ComputationalTreeNode* Instantiate(const ComputationalTreeNode& lhs,            \
                                                   const ComputationalTreeNode& rhs) const          \
                    {                                                                               \
                        return new n (lhs, rhs);                                                    \
                    }                                                                               \
                };                                                                                  \
                                                                                                    \
                static Factory factory;                                                             \
            public:                                                                                 \
                n(const ComputationalTreeNode& lhs, const ComputationalTreeNode& rhs):              \
                    OperationTreeNode(lhs, rhs) {                                                   \
                    };                                                                              \
                                                                                                    \
                n(const OperationTreeNode& copy):OperationTreeNode(copy) { };                       \
                                                                                                    \
                float PerformOperation(float lhs, float rhs) const                                  \
                {                                                                                   \
                    return lhs o rhs;                                                               \
                }                                                                                   \
                                                                                                    \
                ComputationalTreeNode* Clone() const                                                \
                {                                                                                   \
                    return new n(*this);                                                            \
                }                                                                                   \
                                                                                                    \
                void Accept(ComputationalTreeNodeVisitor& visitor)                                  \
                {                                                                                   \
                    OperationTreeNode::Accept(visitor);                                             \
                    visitor.Visit(*this);                                                           \
                }                                                                                   \
                                                                                                    \
            };                                                                                      \


            CREATE_OPERATION_TREE_NODE(AdditionTreeNode, +);
            CREATE_OPERATION_TREE_NODE(SubtractionTreeNode, -);
            CREATE_OPERATION_TREE_NODE(MultiplicationTreeNode, *);
        }
    }
}